using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Reflection;
using System.Text;

using Kenly.DBFramework.Reflection;

namespace Kenly.DBFramework.Gateway
{

    public sealed class WhereClause
    {
        private string _expressionString=" null=null ";
        private static object _entity;

        public string ExpressionString
        {
            get
            {
                return _expressionString;
            }
        }

        public static object Entity
        {
            get
            {
                return _entity;
            }
            set
            {
                if (_entity==null || _entity!=value)
                {
                    _entity = value;
                }
            }
        }

        public WhereClause()
        {
        }

        internal WhereClause(string expressionString)
        {
            _expressionString = expressionString;
        }

        public static WhereClause Equal(string propertyName, object propertyValue)
        {
            Expression exp = Expression.Equal(GetColumnName(propertyName), propertyValue);
            return new WhereClause(exp);
        }

        public static WhereClause Greater(string propertyName, object propertyValue)
        {
            Expression exp = Expression.Greater(GetColumnName(propertyName), propertyValue);
            return new WhereClause(exp); 
        }

        public static WhereClause GreaterEqual(string propertyName, object propertyValue)
        {
            Expression exp = Expression.GreaterEqual(GetColumnName(propertyName), propertyValue);
            return new WhereClause(exp);
        }

        public static WhereClause Less(string propertyName, object propertyValue)
        {
            Expression exp = Expression.Less(GetColumnName(propertyName), propertyValue);
            return new WhereClause(exp); 
        }

        public static WhereClause LessEqual(string propertyName, object propertyValue)
        {
            Expression exp = Expression.LessEqual(GetColumnName(propertyName), propertyValue);
            return new WhereClause(exp); 
        }

        public static WhereClause NotEqual(string propertyName, object propertyValue)
        {
            Expression exp = Expression.NotEqual(GetColumnName(propertyName), propertyValue);
            return new WhereClause(exp);
        }

        public static WhereClause Like(string propertyName, object propertyValue)
        {
            Expression exp = Expression.Like(GetColumnName(propertyName), propertyValue);
            return new WhereClause(exp);
        }

        public static WhereClause In(string propertyName, Array rangeValues)
        {
            Expression exp = Expression.In(GetColumnName(propertyName), rangeValues);
            return new  WhereClause(exp);
        }

        public static WhereClause Between(string propertyName, object startValue, object endValue)
        {
            Expression exp = Expression.Between(GetColumnName(propertyName),startValue,  endValue);
            return new WhereClause(exp);
        }

        #region Build expression

        private static string GetColumnName(string propertyName)
        {
            ColumnAttribute columnAttribute = AttributeUtility.GetColumnAttribute(_entity.GetType(), propertyName);
            if (columnAttribute != null)
            {
                return columnAttribute.ColumnName;
            }
            return null;
        }
       
        
        #endregion


        #region Operator

        public static WhereClause operator &(WhereClause left, WhereClause right)
        {
            if (left == null)
            {
                throw new DBException(MsgResource.InvalidArguments);
            }
            if (right == null)
            {
                throw new DBException(MsgResource.InvalidArguments);
            }
            return BitwiseAnd(left, right);
        }

        public static WhereClause BitwiseAnd(WhereClause left, WhereClause right)
        {
            if (left == null)
            {
                throw new DBException(MsgResource.InvalidArguments);
            }
            if (right == null)
            {
                throw new DBException(MsgResource.InvalidArguments);
            }
            if (string.IsNullOrEmpty(right.ExpressionString))
            {
                return left;
            }
            left._expressionString = "("+left.ExpressionString + " AND " + right.ExpressionString+")";
            return left;
        }

        public static WhereClause operator |(WhereClause left, WhereClause right)
        {
            if (left == null || right == null)
            {
                throw new DBException(MsgResource.InvalidArguments);
            }
            return BitwiseOr(left, right);
        }

        public static WhereClause BitwiseOr(WhereClause left, WhereClause right)
        {
            if (left == null)
            {
                throw new DBException(MsgResource.InvalidArguments);
            }
            if (right == null)
            {
                throw new DBException(MsgResource.InvalidArguments);
            }
            if (string.IsNullOrEmpty(right.ExpressionString))
            {
                return left;
            }
            left._expressionString = "(" + left.ExpressionString + " OR " + right.ExpressionString + ")";
            return left;
        }


        public static implicit operator string(WhereClause whereClause)
        {
            if (whereClause == null)
            {
                throw new DBException(MsgResource.InvalidArguments);
            }
            return whereClause.ExpressionString;
        }

       
        #endregion

        public override string ToString()
        {
            return _expressionString;
        }
    }
}
